package com.lsh.netty.http.httpFileServer;

import io.netty.bootstrap.ServerBootstrap;
import io.netty.channel.ChannelFuture;
import io.netty.channel.ChannelInitializer;
import io.netty.channel.nio.NioEventLoopGroup;
import io.netty.channel.socket.SocketChannel;
import io.netty.channel.socket.nio.NioServerSocketChannel;
import io.netty.handler.codec.http.HttpObjectAggregator;
import io.netty.handler.codec.http.HttpRequestDecoder;
import io.netty.handler.codec.http.HttpResponseEncoder;
import io.netty.handler.logging.LogLevel;
import io.netty.handler.logging.LoggingHandler;
import io.netty.handler.stream.ChunkedWriteHandler;

/**
 * @author ：LiuShihao
 * @date ：Created in 2021/6/2 9:10 上午
 * @desc ：HTTP 服务端开发
 */
public class HttpFileServer {
    private String ipAddress = "127.0.0.1";
    private static final String DEFAULT_URL = "/src/com/exp/netty/";

    public void run(final int port,final String url) throws  Exception{
        NioEventLoopGroup bossGroup = new NioEventLoopGroup();
        NioEventLoopGroup workerGroup = new NioEventLoopGroup();

           try {
               ServerBootstrap b = new ServerBootstrap();
               b.group(bossGroup,workerGroup)
                       .channel(NioServerSocketChannel.class)
                       .handler(new LoggingHandler(LogLevel.INFO))
                       .childHandler(new ChannelInitializer<SocketChannel>() {
                           @Override
                           protected void initChannel(SocketChannel ch) throws Exception {
                               //想ChannelPipeline中添加HTTP请求消息解码器
                               ch.pipeline().addLast("http-decoder",new HttpRequestDecoder());
                               //添加HttpObjectAggregator解码器，作用是将多个消息转换为单一的FullHttpRequest或者FullHttpResponse，
                               // 原因是HTTP解码器在每个HTTP消息中会生成多个消息对象。
                               ch.pipeline().addLast("http-aggregator",new HttpObjectAggregator(65536));
                               //增加HTTP响应编码器，对HTTP响应消息进行编码
                               ch.pipeline().addLast("http-encoder", new HttpResponseEncoder());
                               //添加Chunked handler 作用是支持异步发送大的码流（例如文件传输），但不占用过多的内存，防止发生Java内存溢出错误
                               ch.pipeline().addLast("http-chunked",new ChunkedWriteHandler());
                               //最后添加HTTPFileServerHandler 用于文件服务器的业务逻辑处理
                               ch.pipeline().addLast("fileServerHandler",new HttpFileServerHandler(url));
                           }
                       });
               ChannelFuture future = b.bind(ipAddress, port).sync();
               System.out.println("HTTP 文 件 目 录 服 务 器  启 动 ，网 址 是 ：http://"+ipAddress+":"+port+url);
               future.channel().closeFuture().sync();

           }catch (Exception e){
               System.out.println(e.getMessage());
           }finally {
               bossGroup.shutdownGracefully();
               workerGroup.shutdownGracefully();
           }
    }

    public static void main(String[] args) throws Exception {
        int port = 8080;
        String url = DEFAULT_URL;
        new HttpFileServer().run(port,url);
    }
}
